package com.devshephard.rpcframework.rpc.factory.base;
import com.devshephard.rpcframework.rpc.container.GlobalContainer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class ServicesFactory {

    static Map<Class<?>, Object> map = new ConcurrentHashMap<>();

    static {
        try  {

            //按照注解加载接口
            Set<BeanDefinition> candidateComponents = GlobalContainer.getRpcClientAnnoClassSet();

            for (BeanDefinition candidateComponent : candidateComponents) {

                Class<?> interfaceClass = Class.forName(candidateComponent.getBeanClassName());

                ApplicationContext context = GlobalContainer.getApplicationContext();
                Map<String, ?> xxxServiceMap = context.getBeansOfType(interfaceClass);
                List<?> serviceImplList = new ArrayList<>(xxxServiceMap.values());
                //如果没有实现类,则继续
                if (serviceImplList.size() == 0) {
                    continue;
                }
                //TODO 目前只会调用一个实现类 也就是说一个接口如果有多个实现类,只会调用其中一个实现类
                Object serviceImplObj = serviceImplList.get(0);
                //如果是代理类,则继续
                if(serviceImplObj instanceof Proxy){
                    continue;
                }
                //实现类全限定名
                String packageFullName = serviceImplObj.getClass().getName();
                Class<?> instanceClassImpl = Class.forName(packageFullName);
                map.put(interfaceClass,instanceClassImpl.newInstance());

            }

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static <T> T getService(Class<T> interfaceClass) {

        log.info(interfaceClass.hashCode() + " " +map.get(interfaceClass).toString());

        return (T) map.get(interfaceClass);

    }

}
